﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DDD;
using Xunit;

using Vector2 = DDD.Vector2<float>;

namespace DokiDokiTest {
    public class TestVector2 {

        [Fact]
        public void Test_New1 () {
            var v = new Vector2 ();

            Assert.Equal (2, v.ComponentCount);
            Assert.Equal (0, v.X);
            Assert.Equal (0, v.Y);
            Assert.Equal (0, v[0]);
            Assert.Equal (0, v[1]);
            Assert.Equal (false, v.IsNormalized);
        }

        [Fact]
        public void Test_New2 () {
            var v = new Vector2 (1, 2);

            Assert.Equal (2, v.ComponentCount);
            Assert.Equal (1, v.X);
            Assert.Equal (2, v.Y);
            Assert.Equal (1, v[0]);
            Assert.Equal (2, v[1]);
            Assert.Equal (false, v.IsNormalized);
        }

        [Fact]
        public void Test_New3 () {
            var f = new float[] { 1, 2 };
            var v = new Vector2 (f);
            f[0] = f[1] = 0;

            Assert.Equal (2, v.ComponentCount);
            Assert.Equal (1, v.X);
            Assert.Equal (2, v.Y);
            Assert.Equal (1, v[0]);
            Assert.Equal (2, v[1]);
            Assert.Equal (false, v.IsNormalized);
        }

        [Fact]
        public void Test_New4 () {
            var up = Vector2.Up;
            var down = Vector2.Down;
            var right = Vector2.Right;
            var left = Vector2.Left;

            Assert.Equal (0, up.X);
            Assert.Equal (1, up.Y);
            Assert.Equal (0, down.X);
            Assert.Equal (-1, down.Y);
            Assert.Equal (1, right.X);
            Assert.Equal (0, right.Y);
            Assert.Equal (-1, left.X);
            Assert.Equal (0, left.Y);
        }


        [Fact]
        public void Test_Indexer () {
            var v = new Vector2 ();
            v[0] = 1;
            v[1] = 2;
            Assert.Equal (1, v[0]);
            Assert.Equal (2, v[1]);
        }

        [Fact]
        public void Test_Convertor (){
            var v = new Vector2 (1, 2);
            var ar = new float[] { 1, 2 };

            Assert.Equal (ar, (float[])v);
        }

        [Fact]
        public void Test_Operator () {
            var v1 = new Vector2 (1, 2);
            var v2 = new Vector2 (2, 4);
            var v3 = v1 + v2;
            var v4 = v1 - v2;
            var v5 = v1 * 2;
            var v6 = 2 * v1;
            var v7 = v2 / 2;
            var v8 = -v2;

            Assert.Equal (3, v3.X);
            Assert.Equal (6, v3.Y);
            Assert.Equal (-1, v4.X);
            Assert.Equal (-2, v4.Y);
            Assert.Equal (2, v5.X);
            Assert.Equal (4, v5.Y);
            Assert.Equal (2, v6.X);
            Assert.Equal (4, v6.Y);
            Assert.Equal (1, v7.X);
            Assert.Equal (2, v7.Y);
            Assert.Equal (-2, v8.X);
            Assert.Equal (-4, v8.Y);
        }

        [Fact]
        public void Test_Length () {
            var v = new Vector2 (4, -3);

            Assert.Equal (5, v.Length);
            Assert.Equal (25, v.Length2);
        }

        [Fact]
        public void Test_Normalize () {
            var v1 = new Vector2 (2, 0);
            var v2 = new Vector2 (0, -2);
            var v3 = v1.Normalize ();
            var v4 = v2.Normalize ();

            Assert.Equal (false, v1.IsNormalized);
            Assert.Equal (false, v2.IsNormalized);
            Assert.Equal (true, v3.IsNormalized);
            Assert.Equal (true, v4.IsNormalized);

            Assert.Equal (2, v1.Length);
            Assert.Equal (2, v2.Length);
            Assert.Equal (1, v3.Length, new FloatComparer(0.0001f));
            Assert.Equal (1, v4.Length, new FloatComparer (0.0001f));
        }

        [Fact]
        public void Test_Equals () {
            var v1 = new Vector2 (0, 1.00f);
            var v2 = new Vector2 (0, 1.02f);
            var tmp = GlobalSettings.Tolerance;

            GlobalSettings.Tolerance = 0.1f;

            Assert.True (v1 == v2);
            Assert.True (v1.Equals (v2));
            Assert.True (v1.Equals ((object)v2));
            Assert.False (v1 != v2);

            GlobalSettings.Tolerance = 0.01f;

            Assert.False (v1 == v2);
            Assert.False (v1.Equals (v2));
            Assert.False (v1.Equals ((object)v2));
            Assert.True (v1 != v2);

            GlobalSettings.Tolerance = tmp;
        }
    }
}
